package com.demo.groupchat02;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;

import java.text.SimpleDateFormat;
import java.util.*;


/**
 * @author gy
 * @date 2022/6/11
 */
public class GroupChatServerHandler extends SimpleChannelInboundHandler<String> {

    // 管理 channel 方式三
    // 私聊功能实现，使用 hashMap 管理 channel
//    public static Map<String,Channel> channelMap = new HashMap<>();
//    public static Map<User,Channel> channelMap = new HashMap<>();

    // 管理channel 方式 二
//    public static List<Channel> channels = new ArrayList<Channel>();

    // 定义一个channel 组，管理所有的channel
    // GlobalEventExecutor.
    private static final ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * handlerAdded 表示连接建立，一旦连接，第一个被执行
     * 将当前 channel 加入到 channelGroup
     * @param ctx channel所有的上下文信息
     * @throws Exception
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        // 准备将该客户加入聊天的信息推送给其它在线的客户端
        /**
         * 关键方法：writeAndFlush
         * 该方法会将 channelGroup 中所有的 channel 遍历，并发送 消息，
         * 我们不用自己遍历
         */
        channelGroup.writeAndFlush("[客户端]" + channel.remoteAddress() + " 加入聊天"+
                sdf.format(new Date()) + "\n");
        channelGroup.add(channel);

        // 管理channel 方式 二
//        channels.forEach( channel1 -> channel1.writeAndFlush("[客户端]" + channel.remoteAddress() + " 加入聊天\n"));
//        channels.add(channel);

        // 私聊功能实现
//        channelMap.put("idxxx",channel);
//        channelMap.put(new User(100,"aaa"),channel);

    }

    /**
     * 表示 channel 处于活动状态，提示 xx上线
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println(ctx.channel().remoteAddress() + " 上线了~");
    }

    /**
     * 表示 channel 处于不活动的状态，提示 xx离线
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {

        System.out.println(ctx.channel().remoteAddress() + " 离线了~");
    }

    /**
     * 断开连接，将xx客户离开信息推送给当前在线的客户
     * @param ctx
     * @throws Exception
     */
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        channelGroup.writeAndFlush("[客户端]" + channel.remoteAddress() + " 离开了\n");
        System.out.println("channelGroup size" + channelGroup.size());
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        // 获取当前channel
        Channel channel = ctx.channel();

        // 这时我们遍历channelGroup，根据不同的情况，回送不同的消息
        channelGroup.forEach(ch -> {
            // 不是当前的channel，转发消息，除掉自己的其他用户收到的 由当前 channel发送的消息
            if(channel != ch){
                ch.writeAndFlush("[客户]" + channel.remoteAddress() + " 发送了消息" + msg + "\n");
            }else {
                ch.writeAndFlush("[自己]发送了消息" + msg + "\n");
            }
        });
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        // 关闭通道
        ctx.close();
    }
}
